#ifndef FILE_H
#define FILE_H

#include <cstdint>
#include <vector>
#include <fstream>
#include <sstream>

#include "binarystream.h"
#include "serializable.h"

class EmptyBlocks : public Serializable {
    friend class File;
    public:
        virtual void read(BinaryStream& in) {
            list = in.readPrimitives<u_int32_t>();
        }
        virtual void write(BinaryStream& out) {
            out.writePrimitives<u_int32_t>(list);
        }
        virtual std::string toString() {
           std::stringstream sout;
           sout << "(EmptyBlocks)  ";
           for (u_int32_t block : list) {
               sout << block << " ";
           }
           return sout.str();
        }
    private:
        std::vector<u_int32_t> list;
};

class File {
    public:
        File();
        virtual ~File();

        void addMetadata(Serializable* serializable);

        bool create(const std::string &filename, u_int32_t blockSize);
        bool open(const std::string &filename, u_int32_t blockSize);

        bool read(u_int32_t pos, Serializable& block);
        u_int32_t append(Serializable& block);
        bool write(u_int32_t pos, Serializable& block);
        bool remove(u_int32_t pos);

    private:
        std::vector<Serializable*> metadata;
        EmptyBlocks emptyBlocks;
        std::fstream file;
        u_int32_t blockSize;
        u_int32_t eofPos;

        void readMetadata();
        void writeMetadata();
        u_int32_t getFilePosition(u_int32_t pos) const;
};

#endif // FILE_H
